// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import  { parse } from '@babel/parser';
import traverse from "@babel/traverse";
import generate from "@babel/generator";
import * as types from "@babel/types";

import { 
     FlowBaseAnnotation
} from '@babel/types';

function doPrepare() {
	const activeEditor = vscode.window.activeTextEditor;


	if(!activeEditor) {
		return;
	}

	const text = activeEditor.document.getText();

	const selectionText = activeEditor.document.getText(activeEditor.selection);

	const code = selectionText || text;
	
	const parseAst = parse(code, {
		sourceType: "module",
		plugins: [
			"jsx",
			"typescript",
		  ],
	});


	traverse(parseAst, {
		TSInterfaceDeclaration(path) {
			const swaggerName = `${path.node.id.name}Sw`;
			const body = path.node.body.body || [];
		   
			// const properties = [];
			const properties = body.map((node:any) => {
				const key = node.key.name;
				const isOptional = node.optional;
				const swaggerOptional = isOptional ? 'ApiModelPropertyOptional' : 'ApiModelProperty';
				const type = node.typeAnnotation.typeAnnotation.type;
	
				let typeValue = types.stringTypeAnnotation() as FlowBaseAnnotation;
				let propertyValue = 'IsString';
				switch (type) {
					case 'TSStringKeyword': 
						typeValue = types.stringTypeAnnotation();
						propertyValue = 'IsString';
						break;
					case 'TSNumberKeyword': 
						typeValue = types.numberTypeAnnotation();  
						propertyValue = 'IsNumber';               
						break;
					case 'TSBooleanKeyword': 
						typeValue = types.booleanTypeAnnotation();  
						propertyValue = 'IsBoolean';                
						break;
					default: 
						typeValue = types.anyTypeAnnotation();
						propertyValue = '';
						break;
				}

				const isOptionalDecorator = isOptional ? 'IsOptional' : 'IsNotEmpty';

				const decorators = propertyValue ? [
					types.decorator(
						types.callExpression(
							types.identifier(swaggerOptional),
							[
								types.objectExpression([
									types.objectProperty(
										types.identifier('description'),
										types.stringLiteral('请补充描述')
									)
								])
							]
						)
					),
					types.decorator(
						types.callExpression(
							types.identifier(isOptionalDecorator),
							[]
						)
					),
					types.decorator(
						types.callExpression(
							types.identifier(propertyValue),
							[]
						)
					)
				] : [
					types.decorator(
						types.callExpression(
							types.identifier(swaggerOptional),
							[
								types.objectExpression([
									types.objectProperty(
										types.identifier('description'),
										types.stringLiteral('请补充描述')
									)
								])
							]
						)
					),
					types.decorator(
						types.callExpression(
							types.identifier(isOptionalDecorator),
							[]
						)
					)
				];
			
				return (
					types.classProperty(
						types.identifier(key),
						null,
						types.typeAnnotation(
							typeValue
						),
						decorators
					)
				);
	
			});
	
			const swaggerNode = types.classDeclaration(
					types.identifier(swaggerName),
					null,
					types.classBody(properties)
			);
			
	
			path.replaceWith(swaggerNode);
		},
		// enter(path) {
		//     if(path.isInterfaceDeclaration()) {
		//         console.log('xxxxxxxxxxxxxxx');
		//     }
		//   if (path.isIdentifier()) {
		//     console.log('path.node.name', path.node.name);
		//   }
		// },
	  });
	

	const output = generate(
		parseAst,
		{
			jsescOption: { minimal:true }
		}
	);


	activeEditor.edit(editBuilder => {
		editBuilder.insert(new vscode.Position(activeEditor.selection.end.line + 1, 0), `\n${output.code}\n`);
	});

}


// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
	
	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "I-To-S" is now active!');

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json
	let disposable = vscode.commands.registerCommand('interface-transform.I-To-S', () => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		vscode.window.showInformationMessage('Hello World from xx !');
		doPrepare();
	});

	context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
export function deactivate() {}
